package sokoban;

import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;
import javax.microedition.rms.RecordStoreFullException;
import javax.microedition.rms.RecordStoreNotFoundException;

public class NetMapLoader implements Runnable {

	private String address;

	private Sokoban sokoban;

	private Seeker mapSeeker = new Seeker(Constants.MAP_START,
			Constants.MAP_END);

	public NetMapLoader(Sokoban sokoban) {
		this.sokoban = sokoban;
	}

	private GameMap parse(String s) {
		int x = 0;
		int y = 0;
		GameMap gameMap = new GameMap();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			switch (c) {
			case '.':
				gameMap.setCell(new Point(x, y), Constants.GROUND);
				x++;
				break;
			case '#':
				gameMap.setCell(new Point(x, y), Constants.WALL);
				x++;
				break;
			case '@':
				gameMap.setCell(new Point(x, y), Constants.PLAYER);
				x++;
				break;
			case 'o':
				gameMap.setCell(new Point(x, y), Constants.GOAL);
				x++;
				break;
			case 'x':
				gameMap.setCell(new Point(x, y), Constants.CRATE);
				x++;
				break;
			case '\n':
				if (x > 0) {
					y++;
					x = 0;
				}
				break;
			case '%':
				if (s.startsWith("author", i + 1)) {
					gameMap.setAuthor(s.substring(i + 7, s.indexOf('\n', i))
							.trim());
				} else if (s.startsWith("mapname", i + 1)) {
					gameMap.setTitle(s.substring(i + 8, s.indexOf('\n', i))
							.trim());
				}
				i = s.indexOf('\n', i);
				break;
			}

		}
		return gameMap;
	}

	private Vector extractMaps(String s) {
		Vector maps = new Vector();
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (mapSeeker.isTextMarked(c))
				maps.addElement(mapSeeker.getMarkedText());
		}
		return maps;
	}

	public void loadFromRecordStore() {
		try {
			RecordStore r = RecordStore.openRecordStore("maps", true);
			RecordEnumeration re = r.enumerateRecords(null, null, false);
			while (re.hasNextElement()) {
				String s = new String(re.nextRecord());
				GameMap gameMap = parse(s);
				sokoban.addGameMap(gameMap);
			}
			r.closeRecordStore();

		} catch (RecordStoreException e) {
		}
	}

	public void loadFromNet(String address) {
		this.address = address;
		new Thread(this).start();
	}

	private void saveToRecordStore(String map) {
		try {
			RecordStore r = RecordStore.openRecordStore("maps", true);
			byte[] b = map.toString().getBytes();
			r.addRecord(b, 0, b.length);
			r.closeRecordStore();

		} catch (RecordStoreNotFoundException e) {

		} catch (RecordStoreFullException e) {

		} catch (RecordStoreException e) {

		}
	}

	public void run() {
		StreamConnection connection = null;
		InputStream is = null;
		StringBuffer sb = new StringBuffer();
		try {

			connection = (StreamConnection) Connector.open(address);
			is = connection.openInputStream();
			int i;
			while ((i = is.read()) != -1) {
				sb.append((char) i);
			}
			Vector maps = extractMaps(sb.toString());
			for (i = 0; i < maps.size(); i++) {
				String textMap = (String) maps.elementAt(i);
				GameMap gameMap = parse(textMap);
				saveToRecordStore(textMap);
				sokoban.addGameMap(gameMap);
			}
			sokoban.showInfo(maps.size() + " map(s) loaded.");

		} catch (IOException e) {
			sokoban.showInfo("Error while connecting! Check the address.");
		} finally {
			try {
				if (connection != null) {
					connection.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
			}
		}

	}
}
